package com.tan.lbs.dao.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Xml;

import com.tan.lbs.GamesListActivity;
import com.tan.lbs.dao.GameDAO;
import com.tan.lbs.dao.GameRuleDAO;
import com.tan.lbs.dao.ItemDAO;
import com.tan.lbs.dao.NPCDAO;
import com.tan.lbs.dao.QuestDAO;
import com.tan.lbs.entity.Game;
import com.tan.lbs.entity.GameHeader;
import com.tan.lbs.entity.Item;
import com.tan.lbs.entity.NPC;
import com.tan.lbs.entity.Quest;
import com.tan.lbs.entity.Trigger;
import com.tan.lbs.util.Constants;
import com.tan.lbs.util.SQLiteDatabaseHelper;

public class GameDAOImpl implements GameDAO {

	private Context context;

	public GameDAOImpl(Context context) {
		this.context = context;
	}

	@Override
	public List<GameHeader> findLocalGames() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<GameHeader> findRemoteGames() {
		List<GameHeader> remoteGames = new ArrayList<GameHeader>();

		try {
			remoteGames = getRemoteGameListByXML(context.getResources()
					.getAssets().open("gameList.xml"));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		SQLiteDatabaseHelper dbHelper = new SQLiteDatabaseHelper(context,
				Constants.LOCAL_DB_NAME);
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		for (GameHeader remoteGame : remoteGames) {
			Cursor cursor = db.query("game", new String[] { "gameID",
					"version", "status" }, "gameID=?",
					new String[] { remoteGame.getGameID() }, null, null, null);
			if (cursor.getCount() == 0) {
				// If this game has not started yet, insert the game row into
				// the game table
				ContentValues values = new ContentValues();
				values.put("gameID", remoteGame.getGameID());
				values.put("version", remoteGame.getVersion());
				values.put("status", Game.READY_STATUS);
				db.insert("game", null, values);
				remoteGame.setStatus(Game.READY_STATUS);
			} else {
				cursor.moveToNext();
				String version = cursor.getString(cursor
						.getColumnIndex("version"));
				String status = cursor.getString(cursor
						.getColumnIndex("status"));
				if (!version.equals(remoteGame.getVersion())) {
					remoteGame.setStatus(Game.READY_STATUS);
					dbHelper = new SQLiteDatabaseHelper(context,
							Constants.LOCAL_DB_NAME);
					db = dbHelper.getWritableDatabase();
					ContentValues values = new ContentValues();
					values.put("status", Game.START_STATUS);
					values.put("version", remoteGame.getVersion());
					db.update("game", values, "gameID=?",
							new String[] { remoteGame.getGameID() });
					// do cleaning jobs here , because the game with same
					// gameID
					// has been updated and previous game data should be
					// erased.
				} else {
					remoteGame.setStatus(status);
				}

			}
		}
		db.close();
		return remoteGames;
	}

	@Override
	public Game readGameDetail(String gameID) {
		// TODO Auto-generated method stub
		try {
			return getGameInfoByXML(context.getResources().getAssets()
					.open("gameFiles/" + gameID + "/game.xml"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private List<GameHeader> getRemoteGameListByXML(InputStream inputStream)
			throws Exception {
		List<GameHeader> games = null;
		GameHeader game = null;
		XmlPullParser parser = Xml.newPullParser();
		parser.setInput(inputStream, "UTF-8");

		int event = parser.getEventType();
		while (event != XmlPullParser.END_DOCUMENT) {
			switch (event) {
			case XmlPullParser.START_DOCUMENT:
				games = new ArrayList<GameHeader>();
				break;
			case XmlPullParser.START_TAG:
				if ("game".equals(parser.getName())) {
					game = new GameHeader();
				}
				if (game != null) {
					if ("gameName".equals(parser.getName())) {
						game.setGameName(parser.nextText());
					} else if ("iconID".equals(parser.getName())) {
						game.setIconID(parser.nextText());
					} else if ("description".equals(parser.getName())) {
						game.setDescription(parser.nextText());
					} else if ("gameID".equals(parser.getName())) {
						game.setGameID(parser.nextText());
					} else if ("version".equals(parser.getName())) {
						game.setVersion(parser.nextText());
					}
				}
				break;
			case XmlPullParser.END_TAG:
				if ("game".equals(parser.getName())) {
					games.add(game);
					game = null;
				}
				break;
			}
			event = parser.next();
		}
		return games;
	}

	private Game getGameInfoByXML(InputStream inputStream) throws Exception {
		Game game = null;
		XmlPullParser parser = Xml.newPullParser();
		parser.setInput(inputStream, "UTF-8");

		int event = parser.getEventType();
		while (event != XmlPullParser.END_DOCUMENT) {
			switch (event) {
			case XmlPullParser.START_DOCUMENT:
				break;
			case XmlPullParser.START_TAG:
				if ("game".equals(parser.getName())) {
					game = new Game();
				}
				if (game != null) {
					if ("publishtitle".equals(parser.getName())) {
						game.setPublishTitle(parser.nextText());
					} else if ("publishdescription".equals(parser.getName())) {
						game.setPublishDescription(parser.nextText());
					} else if ("iconID".equals(parser.getName())) {
						game.setIconID(parser.nextText());
					} else if ("gameCoverID".equals(parser.getName())) {
						game.setGameCoverID(parser.nextText());
					} else if ("introduction".equals(parser.getName())) {
						game.setIntroduction(parser.nextText());
					} else if ("ending".equals(parser.getName())) {
						game.setEnding(parser.nextText());
					} else if ("author".equals(parser.getName())) {
						game.setAuthor(parser.nextText());
					} else if ("email".equals(parser.getName())) {
						game.setEmail(parser.nextText());
					} else if ("publishagent".equals(parser.getName())) {
						game.setPublishAgent(parser.nextText());
					}
				}
				break;
			case XmlPullParser.END_TAG:
				if ("game".equals(parser.getName())) {
				}
				break;
			}
			event = parser.next();
		}// end while
		return game;
	}

	@Override
	public void updateGameStatus(String gameID, String status) {
		SQLiteDatabaseHelper dbHelper = new SQLiteDatabaseHelper(context,
				Constants.LOCAL_DB_NAME);
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		ContentValues values = new ContentValues();
		values.put("status", Game.START_STATUS);
		db.update("game", values, "gameID=?", new String[] { gameID });
		db.close();
	}

	@Override
	public void populdateGame(String gameID) {
		SQLiteDatabaseHelper dbHelper = new SQLiteDatabaseHelper(context,
				Constants.LOCAL_DB_NAME);
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		NPCDAO npcDAO = new NPCDAOImpl(context);
		QuestDAO questDAO = new QuestDAOImpl(context);
		ItemDAO itemDAO = new ItemDAOImpl(context);
		GameRuleDAO gameRuleDAO = new GameRuleDAOImpl(context);
		List<NPC> npcs = npcDAO.retrieveNPCs(gameID);
		List<Quest> quests = questDAO.retreiveQuests(gameID);
		List<Item> items = itemDAO.retreiveItems(gameID);
		List<String> triggerIDs = gameRuleDAO.retrieveTriggerIDs(gameID);
		for (NPC npc : npcs) {
			ContentValues values = new ContentValues();
			values.put("gameID", gameID);
			values.put("npcID", npc.getNpcID());
			values.put("status", npc.getChattable());
			db.insert("npc", null, values);
		}
		for(Quest quest : quests) {
			ContentValues values = new ContentValues();
			values.put("gameID", gameID);
			values.put("questID", quest.getQuestID());
			values.put("status", Quest.NOT_CHECKED_IN_STATUS);
			values.put("duration", "--:--:--");
			db.insert("quest", null, values);
		}
		
		for(Item item : items) {
			ContentValues values = new ContentValues();
			values.put("gameID", gameID);
			values.put("itemID", item.getItemID());
			values.put("status",item.getPickable());
			db.insert("item", null, values);
		}
		
		for(String triggerID : triggerIDs) {
			ContentValues values = new ContentValues();
			values.put("gameID", gameID);
			values.put("triggerID", triggerID);
			values.put("status", Trigger.NOT_TRIGGER_STATUS);
			db.insert("trigger", null, values);
		}
		
		//retrieve all triggers
		db.close();
	}
}
